home *** CD-ROM | disk | FTP | other *** search
- /*========================================================================
- Module: Mstr_Env (Master Environment Access)
- Version: 1.00 11-Mar-1989
-
- Written by Scott Robert Ladd.
-
- This software has been released into the public domain;
- no warranties are expressed or implied.
-
- This source code will work with most MS-DOS C compilers. It has been
- tested with Microsoft C 5.1 and QuickC 2.0, Borland Turbo C 2.0, and
- Zortech C v1.07.
- =========================================================================*/
-
- #include "dos.h" /* _psp definition */
- #include "stddef.h" /* NULL and other standard definitions */
- #include "string.h" /* string functions */
- #include "mstr_env.h" /* to get prototypes */
-
- /* define a macro for MSC and QC */
- #if defined(_QC) || defined (_MSC)
- #define MK_FP(seg,off) ((void far *)(((long)(seg) << 16L) | (long)(off)))
- #endif
-
- /*
- internal MS-DOS structures
- --------------------------
- */
-
- typedef struct
- {
- char reserved1[22];
- unsigned par_seg; /* segment of the parent of the current program */
- char reserved2[20];
- unsigned env_seg; /* environment segment for current program */
- }
- PSP;
-
- /*-----------------
- IMPORTANT NOTE!
- -----------------------------------------------------------------------
- The MCB structure must be compiled with byte, not word, alignment. In
- Microsoft C, this is accomplished through the use of the pack pragma.
- By default, Turbo C uses byte alignment. When compiling this module
- with Zortech C, the -a switch must be used to get byte alignment.
- ----------------------------------------------------------------------- */
-
- #if defined(_QC) || defined(_MSC)
- #pragma pack(1)
- #endif
-
- typedef struct
- {
- char status; /* indicates whether this block is in chain */
- unsigned owner_PSP; /* the PSP segment of this block's owner */
- unsigned len; /* the size (in paragraphs) of this memory block */
- }
- MCB;
-
- #if defined(_QC) || defined(_MSC)
- #pragma pack()
- #endif
-
- /*
- global declarations
- -------------------
- */
-
- char far * env_ptr; /* pointer to first byte of global env. */
- static unsigned env_len; /* length of global environment */
-
- static int initialized = 0; /* indicates whether the module is initialized */
-
- static char s[256]; /* internal buffer used for strings */
-
- static void m_findenv(void); /* internal function used to find the master
- environment */
-
- #define NUL '\x00' /* the nul (zero) character used by C as a string
- terminator */
-
- /*
- function definitions
- --------------------
- */
-
- /*
- function: m_getenv
-
- purpose: retrieves an environment variable's value
-
- parameters: name -- the name of the variable whose value is sought
-
- returns: A pointer to the value of the requested variable, or NULL if the
- variable was not found.
-
- NOTE: the return value is a pointer to a static char array in
- this module. Thus the previous value is destroyed each time this
- function is called.
- */
-
- char * m_getenv(char * name)
- {
- char far * e;
- char * n;
- int i;
-
- /* check for initialization */
- if (!initialized)
- m_findenv();
-
- e = env_ptr;
-
- /* search for name */
- while (*e)
- {
- n = name;
-
- while ((*e == *n) && (*e != '=') && (*e != NUL) && (*n != NUL))
- {
- ++e;
- ++n;
- }
-
- if ((*n == NUL) && (*e == '=')) /* name found */
- {
- /* copy variable value to s */
- ++e;
-
- /* strcpy() cannot be used because pointer sizes may differ */
- for (i = 0; (i < 256) && (*e != NUL); ++i)
- {
- s[i] = *e;
- ++e;
- }
-
- if (i < 256)
- s[i] = NUL;
-
- return s; /* contains value of name */
- }
-
- /* skip to the next environment variable */
- while (*e != NUL)
- ++e;
-
- ++e;
- }
-
- /* name wasn't found */
- return NULL;
- }
-
- /*
- function: m_putenv
-
- purpose: stores an environment variable
-
- parameters: name -- name of the variable to be stored
- text -- the variable's value
-
- returns: 0 if the variable was stored
- 1 if not
- */
-
- int m_putenv(char *name, char *text)
- {
- char far * e;
- unsigned l = 0;
- char * sptr;
-
- /* check for initialization */
- if (!initialized)
- m_findenv();
-
- e = env_ptr;
-
- /* check to see that the storage required is < 256 bytes */
- if ((strlen(name) + 2 + strlen(text)) > 256)
- return 1;
-
- /* make a complete environment string from the components given */
- strcpy(s,name);
- strupr(s);
- strcat(s,"=");
- strcat(s,text);
-
- /* delete any existing variables of the same name */
- m_delenv(name);
-
- /* find the end of the current variables (mark by two nulls) */
- e = env_ptr;
- l = 0;
-
- /* loop until two NULs are found, signifying the end of the environment */
- while (!((*e == NUL) && (*(e+1) == NUL)))
- {
- ++e;
- ++l;
- }
-
- /* get the amount of remaining space */
- l = env_len - l - 1;
-
- /* if the new variable won't fit, return an error */
- if (l < strlen(s))
- return 1;
-
- sptr = s;
-
- /* otherwise, copy s onto the end of the current environment */
- ++e;
-
- while (*sptr != NUL)
- *e++ = *sptr++;
-
- /* end the environment with two NUL bytes */
- *e = NUL;
- *(e + 1) = NUL;
-
- /* it worked! */
- return 0;
- }
-
- /*
- function: m_delgenv
-
- purpose: deletes an environment variable
-
- parameters: name -- the name of the variable to be deleted
-
- returns: 1 if the variable could not be deleted or does not exit
- 0 upon success
- */
- int m_delenv(char *name)
- {
- char far * e1; /* used in search & marks beginning of next variable */
- char far * e2; /* marks beginning of the variable */
- char * n; /* name pointer used in search */
- int searching = 1; /* flag to indicate search end */
-
- /* has the module been initialized? If not, do it! */
- if (!initialized)
- m_findenv();
-
- e1 = env_ptr;
-
- /* find the beginning of the variable to be deleted */
- while ((*e1 != NUL) && (searching))
- {
- n = name;
- e2 = e1;
-
- while ((*e1 == *n) && (*e1 != '=') && (*e1 != NUL) && (*n != NUL))
- {
- ++e1;
- ++n;
- }
-
- if ((!*n) && (*e1 == '='))
- searching = 0; /* the variable we want was found! */
-
- while (*e1 != NUL)
- ++e1;
-
- ++e1;
- }
-
- /* if name wasn't found, return with an error */
- if ((*e1 == NUL) && (searching))
- return 1;
-
- /* otherwise, copy the remainder of the environment over name */
- while (!((*e1 == NUL) && (*(e1+1) == NUL)))
- {
- *e2 = *e1;
- e2++;
- e1++;
- }
-
- /* end the environment with double NUL bytes */
- *e2 = NUL;
- *(e2 + 1) = NUL;
-
- /* it worked */
- return 0;
- }
-
- /*
- function: m_findenv
-
- purpose: locates the global environment and sets a pointer to it
-
- parameters: none
-
- returns: nothing
- */
-
- static void m_findenv()
- {
- union REGS regs;
- struct SREGS sregs;
- int far * SEGptr; /* set to address of segment of first MCB */
- MCB far * CONFIGmcb; /* set to address of CONFIG's MCB */
- MCB far * SHELLmcb; /* set to address of COMMAND.COM's MCB */
- MCB far * ENVmcb; /* set to address of environment's MCB */
- PSP far * SHELLpsp; /* set to address of COMMAND.COM's PSP */
-
- regs.h.ah = 0x52;
- intdosx(®s,®s,&sregs);
-
- SEGptr = MK_FP(sregs.es, regs.x.bx - 2);
-
- CONFIGmcb = MK_FP(*SEGptr,0);
-
- SHELLpsp = MK_FP(FP_SEG(CONFIGmcb) + CONFIGmcb->len + 2, 0);
-
- if (SHELLpsp->env_seg == 0)
- {
- /* the environment is in the block AFTER the parent program */
- SHELLmcb = MK_FP(FP_SEG(CONFIGmcb) + CONFIGmcb->len + 1, 0);
- env_ptr = MK_FP(FP_SEG(SHELLmcb) + SHELLmcb->len + 2, 0);
- }
- else
- {
- /* otherwise, we have a direct pointer to the environment block */
- env_ptr = MK_FP(SHELLpsp->env_seg, 0);
- }
-
- /* set a ppointer to the MCB of the environment block */
- ENVmcb = MK_FP(FP_SEG(env_ptr) - 1, 0);
-
- /* calculate the length of the environment */
- env_len = ENVmcb->len * 16;
-
- /* set the initialization flag */
- initialized = 1;
- }